import java.sql.*;

public class LogisticaEntrega {

	private static final String DELIMITADOR = "\\|";
	
	/**
	 * Retornos default.
	 */
	private static final String OK = "OK|";
	private static final String ERR = "ERR|";

	/**
	 * Retorno do CalcularPrazoDeEntrega.
	 */
	private static final String ERR_1_ENDERECO_INVALIDO = "ERR|EnderecoInvalido";
	private static final String ERR_1_PRODUTO_INVALIDO = "ERR|ProdutoInvalido";
	private static final String ERR_1_ENDERECO_NAO_ATENDIDO = "ERR|EnderecoNaoAtendido";
	private static final String ERR_1_PARAMETRO_NULO = "ERR|ParametroNulo";
	
	/*
	 * Retorno de EntregaDeProduto.
	 */
	private static final String ERR_2_PRODUTO_INVALIDO = "ERR|ProdutoInvalido";
	private static final String ERR_2_CLIENTE_INVALIDO = "ERR|ClienteInvalido";
	private static final String ERR_2_PARAMETRO_NULO = "ERR|ParametroNulo";

	/**
	 * Retornos do ObterEstadoDoPedido.
	 */
	private static final String OK_3_AGUARDANDO = "OK|ProdutoAguardandoColeta";
	private static final String OK_3_EM_TRANSITO = "OK|ProdutoEmTransito";
	private static final String OK_3_ENTREGUE = "OK|ProdutoEntregue";
	private static final String ERR_3_NAO_ENTREGUE = "ERR|ErroNaEntrega";
	private static final String ERR_3_PROTOCOLO_INVALIDO = "ERR|ProtocoloInvalido";
	
	/**
	 * Retornos de ObterListaDeProtocolos.
	 */
	private static final String ERR_4_CLIENTE_INVALIDO = "ERR|ClienteInvalido";

	/**
	 * Calcula o prazo de entrega de um pedido.
	 * 
	 * @param endereco
	 *            Endereco de entrega.
	 * @param produtos
	 *            Lista de produtos separados pelo delimitador.
	 * @return Prazo de entrega em dias.
	 */
	public String calculaPrazo(String endereco, String produtos) {
		// Variaveis locais
		String sql = null;
		int prazo = 0;
		int quantidade = 0;
		String returnString = null;
		ResultSet result = null;
		String[] prodList = null;
		Statement stat = null;
		Connection conn = DBConnection.getConnection();
		int passagem = 0;

		sql = "select max(tempo_de_preparo) as prazo, count(*) as quantidade from RequisicaoDeProduto where ";

		// Lista de produtos
		prodList = produtos.split(LogisticaEntrega.DELIMITADOR);

		for (int i = 0; i < prodList.length; i++) {
			if(prodList[i].isEmpty()){
				return LogisticaEntrega.ERR_1_PARAMETRO_NULO;
			}
			sql += "id_produto = " + prodList[i] + " OR ";
		}

		sql = sql.substring(0, sql.length() - 3);

		// Debug
		System.out.println(sql);

		try {
			stat = conn.createStatement();
			result = stat.executeQuery(sql);

			// Vai para o primeiro resultado
			result.next();

			prazo = result.getInt(1);
			quantidade = result.getInt(2);

			result.close();

			// Verifica se algum produto é invalido
			if (quantidade < prodList.length) {
				returnString = LogisticaEntrega.ERR_1_PRODUTO_INVALIDO;
			} 
			else {
				sql = "select tempo_de_envio, disponibilidade from PrazoDeEntrega where id_endereco = ";
				sql += endereco;

				// Debug
				System.out.println(sql);
			
				passagem = 1;
				
				result = stat.executeQuery(sql);

				// Verifica se o endereco é valido
				if (result.next()) {
					if(result.getByte(2) == 0){
						returnString = LogisticaEntrega.ERR_1_ENDERECO_NAO_ATENDIDO;
					}
					else{
						prazo += result.getInt(1);
						returnString = LogisticaEntrega.OK + prazo;
					}
				} 
				else {
					returnString = LogisticaEntrega.ERR_1_ENDERECO_INVALIDO;
				}
			}

		} catch (SQLException e) {
			if(passagem == 0){
				returnString = LogisticaEntrega.ERR_1_PRODUTO_INVALIDO;
			}
			else {
				returnString = LogisticaEntrega.ERR_1_ENDERECO_INVALIDO;
			}
			e.printStackTrace();
		}

		return returnString;
	}

	/**
	 * Efetua a entrega de um pedido.
	 * 
	 * @param endereco Endereco de entrega.
	 * @param produtos Lista de produtos.
	 * @param remetente Nome do remetente.
	 * @param destinatario Nome do destinatario.
	 * @param idCliente Identificador unico do cliente.
	 * @return Protocolo de entrega.
	 */
	public String entregaProdutos(String endereco, String produtos,
			String remetente, String destinatario, int idCliente) {
		// Variaveis locais
		ResultSet result = null;
		int protocolo = 0;
		Connection conn = null;
		Statement stat = null;
		String sql = null;
		String[] prodList = null;
		
		if(!this.validaEntregaParametros(endereco, produtos, remetente, destinatario, idCliente)){
			return LogisticaEntrega.ERR_2_PARAMETRO_NULO;
		}
		
		prodList = produtos.split(LogisticaEntrega.DELIMITADOR);
		
		sql = "select count(*) as quantidade from RequisicaoDeProduto where ";
		
		for (int i = 0; i < prodList.length; i++) {
			if(prodList[i].isEmpty()){
				return LogisticaEntrega.ERR_2_PARAMETRO_NULO;
			}
			sql += "id_produto = " + prodList[i] + " OR ";
		}
		
		sql = sql.substring(0, sql.length() - 3);
		
		// Debug
		System.out.println(sql);
		
		try {		
			conn = DBConnection.getConnection();
			stat = conn.createStatement();
			
			result = stat.executeQuery(sql);
			
			// Verifica se todos os produtos existem
			result.next();
			if(result.getInt(1) < prodList.length){
				result.close();
				return LogisticaEntrega.ERR_2_PRODUTO_INVALIDO;
			}
			result.close();
			
			sql = "insert into InformacoesDeEntrega values (0,'" + endereco
					+ "', '" + remetente + "', '" + destinatario + "', "
					+ idCliente + ", 0)";
	
			// Debug
			System.out.println(sql);

			// Recupera o numero de protocolo gerado
			stat.executeUpdate(sql, Statement.RETURN_GENERATED_KEYS);
			result = stat.getGeneratedKeys();
			result.next();
			protocolo = result.getInt(1);

			// Armazena os produtos associados ao protocolo
			for(int i=0; i<prodList.length; i++){
				sql = "insert into ProdutosDaEntrega values (" + protocolo + ", " + prodList[i] + ")";
				stat.execute(sql);
			}

		} catch (SQLException e) {
			e.printStackTrace();
			return LogisticaEntrega.ERR;
		}

		return LogisticaEntrega.OK + Integer.toString(protocolo);
	}
	
	/**
	 * Valida os parametros do metodo de entrega de produtos.
	 */
	private boolean validaEntregaParametros(String endereco, String produtos,
			String remetente, String destinatario, int idCliente){
		if(endereco == null || endereco.isEmpty() || 
		   produtos == null || produtos.isEmpty() || 
		   remetente == null || remetente.isEmpty() ||
		   destinatario == null || destinatario.isEmpty()){
			return false;
		}
		
		return true;
	}

	/**
	 * Verifica a situacao da entrega dado um protocolo.
	 * 
	 * @param protocolo
	 * @return
	 */
	public String verificaSituacaoEntrega(int protocolo) {
		// Variaveis locais
		String sql = null;
		ResultSet result = null;
		int status = 0;
		String statusStr = null;
		Connection conn = null;
		
		sql = "select status from InformacoesDeEntrega where protocolo = " + protocolo;

		// Debug
		System.out.println(sql);

		try {
			conn = DBConnection.getConnection();
			Statement stat = conn.createStatement();
			result = stat.executeQuery(sql);

			if(result.first()){
				status = result.getInt(1);
			}
			else {
				return LogisticaEntrega.ERR_3_PROTOCOLO_INVALIDO;
			}

			switch (status) {
			case 0:
				statusStr = LogisticaEntrega.OK_3_AGUARDANDO;
				break;
			case 1:
				statusStr = LogisticaEntrega.OK_3_EM_TRANSITO;
				break;
			case 2:
				statusStr = LogisticaEntrega.OK_3_ENTREGUE;
				break;
			case 3:
				statusStr = LogisticaEntrega.ERR_3_NAO_ENTREGUE;
				break;
			}

		} catch (SQLException e) {
			e.printStackTrace();
			return LogisticaEntrega.ERR;
		}

		return statusStr;
	}
	
	/**
	 * Obtem uma lista de protocolos
	 * 
	 * @param idCliente
	 * @return
	 */
	public String obterListaDeProtocolos(String idCliente){
		// Variaveis locais
		String sql = null;
		ResultSet result = null;
		int status = 0;
		String protocoloList = "";
		Connection conn = null;
		
		if(idCliente == null || idCliente.isEmpty()){
			return LogisticaEntrega.ERR_4_CLIENTE_INVALIDO;
		}
		
		sql = "select protocolo from InformacoesDeEntrega where id_cliente = " + idCliente;

		// Debug
		System.out.println(sql);

		try {
			conn = DBConnection.getConnection();
			Statement stat = conn.createStatement();
			result = stat.executeQuery(sql);

			protocoloList = LogisticaEntrega.OK;
			
			while(result.next()){
				protocoloList += result.getInt(1) + "|";
			}
			
			if(!protocoloList.isEmpty()){
				protocoloList = protocoloList.substring(0, protocoloList.length() - 1);
			}

		} catch (SQLException e) {
			e.printStackTrace();
			return LogisticaEntrega.ERR;
		}

		return protocoloList;
	}
}

